package com.platform.qujia.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.platform.qujia.anno.SimpleRepeatedReqLimit;
import com.platform.qujia.constantEnum.DecimalConstant;
import com.platform.qujia.constantEnum.integralTypeEnum;
import com.platform.qujia.dao.*;
import com.platform.qujia.enums.*;
import com.platform.qujia.handle.PayOrderHandle;
import com.platform.qujia.param.request.*;
import com.platform.qujia.pay.strategy.YunhuaChannel;
import com.platform.qujia.pojo.*;
import com.platform.qujia.pojo.dto.DivideAccountsSettingDto;
import com.platform.qujia.pojo.dto.ElectronicCardSubRes;
import com.platform.qujia.pojo.dto.IntegralDeductionActivityDto;
import com.platform.qujia.service.*;
import com.platform.qujia.service.impl.SxfCallbackServiceImpl;
import com.platform.qujia.utils.*;
import com.platform.qujia.utils.exception.CustomException;
import com.platform.qujia.utils.exception.EndingException;
import com.platform.qujia.utils.jinkong.JKPayParam;
import com.platform.qujia.utils.jinkong.JKPayUtil;
import com.platform.qujia.utils.sxfpay.SXFPayParam;
import com.platform.qujia.utils.sxfpay.SXFPayUtil;
import com.platform.qujia.utils.tonglianpay.TLPayParam;
import com.platform.qujia.utils.tonglianpay.TLPayUtil;
import com.platform.qujia.utils.tonglianpay.tlfusclasspay.TLFusClassPayUtil;
import com.platform.qujia.utils.tonglianpay.tlfusclasspay.struct.body.TLFusClassPayParam;
import com.platform.qujia.utils.weixinapp.WxPushUtil;
import com.platform.qujia.utils.yunHua.YunHuaParam;
import com.platform.qujia.utils.yunHua.yunHuaPayUtils;
import com.platform.qujia.utils.yunpay.SBPayParam;
import com.platform.qujia.utils.yunpay.SBPayUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/***
 * <Title> QuJiaPayController </Title>
 * <Description> 趣加 新版小程序订单 App生成订单，与调用第三方支付控制层 </Description>
 * <Date>2021年10月28日</Date>
 */

@RestController
@Api(tags = "趣加App组合支付")
//@QuJiaRequest()
@CrossOrigin
@Slf4j
public class QuJiaCombinedPayController {

    private static Logger logger = (Logger) LoggerFactory.getLogger(QuJiaCombinedPayController.class);
    @Autowired
    private QuJiaPayV2Controller quJiaPayV2Controller;
    @Resource
    private PayOrderMapper payOrderMapper;
    @Resource
    private EnterpriseService enterpriseService;

    @Autowired
    private IntegralDeductionActivityService integralDeductionActivityService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @ApiOperation(value = "创建组合支付订单", httpMethod = "POST", notes = "创建组合支付订单")
    @PostMapping(value = "/createCombinedOrder2", produces = "application/json;charset=UTF-8")
    @Transactional(rollbackFor = Exception.class)
    public String createCombinedOrder2(@RequestBody CombinedPayOrderRequest request) {
        Station station = enterpriseService.selectStationById(request.getStationId());
        if (Objects.isNull(station)) {
            return ResultData.errorJson("油站不存在");
        }
        try {
            if (StringUtils.isEmpty(request.getOrderNo()) && StringUtils.isEmpty(request.getPayType()) && ObjectUtils.isEmpty(request.isGenericPay())) {

                throw new EndingException("缺少第一笔订单参数");
            }
            String orderNoFirst = request.getOrderNo();
            PayOrder payOrder1 = payOrderMapper.selectByOrdNo(orderNoFirst);
            //region 判断是否已创建过组合支付订单，有将原子订单剥离
            if (payOrder1.getOrderMergeNo() != null) {
                PayOrder orderMerge = payOrderMapper.selectByOrdNo(payOrder1.getOrderMergeNo());
                orderMerge.setOrderMergeNo(null);
                payOrderMapper.updatePayOrder(orderMerge);
            }
            //endregion


            Integer enterpriseId = station.getEnterpriseId();//油企id

            Double receivableAmt = payOrder1.getReceivableAmt();//第一笔应付金额
            Double amt = payOrder1.getAmt();//第一笔实付金额
            Double orderLiters = new Double(payOrder1.getOrderLiters());//第一笔油升
            Double dzkAmt = payOrder1.getDzkAmt();//第一笔油升

            IntegralDeductionActivityDto integralDeductionActivityDto = new IntegralDeductionActivityDto();
            // 计算 积分抵扣现金
            if("1".equals(request.getIsIntegral())){
                IntegralDeductionActivityDto req = new IntegralDeductionActivityDto();
                req.setUserId(payOrder1.getConsumerId().longValue());
                req.setStationId(payOrder1.getStationId().longValue());
                req.setOrderNo(payOrder1.getOrderNo());
                req.setAmt(BigDecimal.valueOf(payOrder1.getAmt()));
                integralDeductionActivityDto = integralDeductionActivityService.selectIntegralDeductionActivity(req);
            }

            LinkedHashMap<String, String> returnMap = new LinkedHashMap<>();
            returnMap.put("zhzf", orderNoFirst);

            String orderNoFinal = null;
            PayOrder payOrderFinal = null;

            Boolean notOtherPayments = true;
            List<PayOrderRequest> extraPayOrderList = request.getExtraPayOrderList();
            if (extraPayOrderList.size() != 1) {
                throw new EndingException("目前只支持两种支付方式");
            }

            BigDecimal oilPirce = new BigDecimal(payOrder1.getOilPirce());
            for (PayOrderRequest payOrderRequest : extraPayOrderList) {
                payOrderRequest.setEnterpriseId(enterpriseId);
                payOrderRequest.setConsumerId(payOrder1.getConsumerId());
                payOrderRequest.setReceivableAmt(request.getReceivableAmt().toString());
                payOrderRequest.setCustomerPhone(payOrder1.getCustomerPhone());
                payOrderRequest.setCustomerName(payOrder1.getCustomerGrade());

                if ("wx".equals(payOrderRequest.getPayType()) && notOtherPayments) {
                    notOtherPayments = false;
                    String orderNotContainActivity = quJiaPayV2Controller.createOrderNotContainActivityForWx(payOrderRequest);


                    orderNoFinal = getOrderNo(orderNotContainActivity, "orderNo");
                    payOrderFinal = payOrderMapper.selectByOrdNo(orderNoFinal);
                    BigDecimal receivableAmt2 = new BigDecimal(payOrderFinal.getReceivableAmt());
                    BigDecimal oilLitersNew = receivableAmt2.divide(oilPirce, 4, BigDecimal.ROUND_HALF_UP); //加油升数

                    receivableAmt -= receivableAmt2.doubleValue();//第一笔应付金额
                    amt -= receivableAmt2.doubleValue();//第一笔实付金额
                    orderLiters -= oilLitersNew.doubleValue();//第一笔油升
                    dzkAmt -= receivableAmt2.doubleValue();//第一笔油升

                    returnMap.put(payOrderRequest.getPayType(), orderNoFinal);

                    payOrderFinal.setPayType(payOrderRequest.getPayType());
                    extracted(payOrder1, payOrderFinal, oilLitersNew);

                    payOrderMapper.updatePayOrderReceivableAmt(payOrderFinal);

                } else if ("zfb".equals(payOrderRequest.getPayType()) && notOtherPayments) {
                    notOtherPayments = false;
                    String orderNotContainActivity = quJiaPayV2Controller.createOrderNotContainActivityForWx(payOrderRequest);

                    orderNoFinal = getOrderNo(orderNotContainActivity, "orderNo");
                    payOrderFinal = payOrderMapper.selectByOrdNo(orderNoFinal);
                    BigDecimal receivableAmt2 = new BigDecimal(payOrderFinal.getReceivableAmt());
                    BigDecimal oilLitersNew = receivableAmt2.divide(oilPirce, 4, BigDecimal.ROUND_HALF_UP); //加油升数

                    receivableAmt -= receivableAmt2.doubleValue();//第一笔应付金额
                    amt -= receivableAmt2.doubleValue();//第一笔实付金额
                    orderLiters -= oilLitersNew.doubleValue();//第一笔油升
                    dzkAmt -= receivableAmt2.doubleValue();//第一笔油升

                    payOrderFinal.setPayType(payOrderRequest.getPayType());
                    extracted(payOrder1, payOrderFinal, oilLitersNew);

                    payOrderMapper.updatePayOrderReceivableAmt(payOrderFinal);
                } else if ("zfb".equals(payOrderRequest.getPayType()) || "wx".equals(payOrderRequest.getPayType())) {
                    throw new EndingException("子订单中存在支付宝和微信互斥");
                } else {
                    String orderNotContainActivity = quJiaPayV2Controller.createOrderNotContainActivityForWx(payOrderRequest);
                    String orderNo = getOrderNo(orderNotContainActivity, "orderNo");
                    payOrderFinal = payOrderMapper.selectByOrdNo(orderNo);
                    BigDecimal receivableAmt2 = new BigDecimal(payOrderFinal.getReceivableAmt());
                    BigDecimal oilLitersNew = receivableAmt2.divide(oilPirce, 4, BigDecimal.ROUND_HALF_UP); //加油升数

                    receivableAmt -= receivableAmt2.doubleValue();//第一笔应付金额
                    amt -= receivableAmt2.doubleValue();//第一笔实付金额
                    orderLiters -= oilLitersNew.doubleValue();//第一笔油升
                    dzkAmt -= receivableAmt2.doubleValue();//第一笔油升

                    returnMap.put(payOrderRequest.getPayType(), orderNo);

                    payOrderFinal.setPayType(payOrderRequest.getPayType());
                    extracted(payOrder1, payOrderFinal, oilLitersNew);

                    payOrderMapper.updatePayOrderReceivableAmt(payOrderFinal);
                }
            }
            if (notOtherPayments) {
                throw new EndingException("不包含第三方支付");
            }

            List<String> orderNos = new ArrayList<>(returnMap.values());
            PayOrder payOrder = new PayOrder();
            payOrder.setOrderNo(orderNoFirst);
            payOrder.setReceivableAmt(receivableAmt);
            payOrder.setOrderLiters(orderLiters.toString());
            payOrder.setAmt(amt);
            payOrder.setPayType("dzk");
            payOrder.setDzkAmt(dzkAmt);
            // 积分抵扣现金
            if(Objects.nonNull(integralDeductionActivityDto) && Objects.nonNull(integralDeductionActivityDto.getIntegralDeductionAmt())){
                payOrder.setIntegralActivityId(integralDeductionActivityDto.getIntegralActivityId());
                payOrder.setIntegralDeductionNum(integralDeductionActivityDto.getIntegralDeductionNum());
                payOrder.setIntegralDeductionAmt(integralDeductionActivityDto.getIntegralDeductionAmt());
                payOrder.setAmt(payOrder.getAmt() - integralDeductionActivityDto.getIntegralDeductionAmt().doubleValue());
            }
//            if (payOrderMapper.updateOrderMergeNoByOrderNos(orderNoFinal, orderNos) > 0)  {
            if ((payOrderMapper.updateOrderMergeNoByOrderNos(orderNoFinal, orderNos) > 0) && (payOrderMapper.updatePayOrderReceivableAmt(payOrder) > 0)) {
                redisTemplate.opsForValue().set("order:combined_order:".concat(orderNoFirst), request.getPayType().concat(",").concat(request.isGenericPay() ? "0" : "1"), 1, TimeUnit.DAYS);


                Double commission = payOrderFinal.getCommission();
                Double receivableAmt1 = payOrderFinal.getReceivableAmt();
                boolean channelFeePayer = payOrderFinal.getChannelFeePayer().equals("0");


                HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
                objectObjectHashMap.put("orderNo", orderNoFinal);
                objectObjectHashMap.put("commission", commission);
                objectObjectHashMap.put("isShowPaymentAmtCommission", (channelFeePayer && station.getIsShowPaymentCommission() == 1) ? 1 : 0);

                objectObjectHashMap.put("amt", ( channelFeePayer) ? (receivableAmt1 + commission) : receivableAmt1);


                return ResultData.successJson(objectObjectHashMap);
            }
            throw new EndingException("创建组合订单信息失败");
        } catch (Exception e) {
            logger.error("/createCombinedOrder-", e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return ResultData.errorJson(e.getMessage());
        }
    }

    private static void extracted(PayOrder payOrder1, PayOrder payOrderFinal, BigDecimal oilLitersNew) {
        payOrderFinal.setOrderLiters(oilLitersNew.toString());
        payOrderFinal.setConsumer(payOrder1.getConsumer());
        payOrderFinal.setOilGun(payOrder1.getOilGun());
        payOrderFinal.setOilName(payOrder1.getOilName());
        payOrderFinal.setOilPirce(payOrder1.getOilPirce());
        payOrderFinal.setOilType(payOrder1.getOilType());
        payOrderFinal.setWxAmt(payOrderFinal.getAmt());
        payOrderFinal.setOrderType(payOrder1.getOrderType());
        payOrderFinal.setUtmSource("9");
    }

    private String getOrderNo(String orderNotContainActivity, String paramName) throws EndingException {

        JSONObject jsonOrderNotContainActivity = JSONObject.parseObject(orderNotContainActivity);
        if (jsonOrderNotContainActivity.get("retCode").equals(0)) {
            JSONObject jsonData = (JSONObject) jsonOrderNotContainActivity.get("data");
            String retVal = jsonData.get(paramName).toString();
            if (retVal != null) {
                return retVal;
            }
        }
        throw new EndingException("创建订单失败");
    }

    //    /**
//     * 组合支付随行付回调
//     */
//    @Transactional
//    public String sxfPayCallbackV2Withdraw(JSONObject request, String ordNo, String couponUserId) {
//        try {
//            String s = redisTemplate.opsForValue().get("order:combined_order:".concat(ordNo));
//            String[] split = s.split(",");
//            if(split.length!=2){
//                throw new EndingException("缺少第一笔订单参数");
//            }
//            quJiaPayV2Controller.sxfPayCallbackV2Withdraw(request);
//            quJiaPayV2Controller.newDzkCouponPaySetV3(ordNo, couponUserId,split[0],split[1].equals("0"));
//            return SxfCallbackServiceImpl.SUCCESS_RETURN_VALUE;
//        } catch (Exception e) {
//            logger.error("[QuJiaCombinedPayController.sxfPayCallbackV2Withdraw]-", e);
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return SxfCallbackServiceImpl.FAIL_RETURN_VALUE;
//        }
//    }
//
//    /**
//     * 组合支付云华回调
//     */
//    @Transactional
//    public void yunHuaNoticeWithdraw(HttpServletRequest request, HttpServletResponse response, String ordNo, String couponUserId) {
//        try {
//            String s = redisTemplate.opsForValue().get("order:combined_order:".concat(ordNo));
//            String[] split = s.split(",");
//            if(split.length!=2){
//                throw new EndingException("缺少第一笔订单参数");
//            }
//            quJiaPayV2Controller.yunHuaNoticeWithdraw(request, response);
//            quJiaPayV2Controller.newDzkCouponPaySetV3(ordNo, couponUserId,split[0],split[1].equals("0"));
//        } catch (Exception e) {
//            logger.error("[QuJiaCombinedPayController.yunHuaNoticeWithdraw]-", e);
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//        }
//    }
    private String generateOrdNo() {
        Random random = new Random();
        String result = "";
        for (int i = 0; i < 6; i++) {
            result += random.nextInt(10);
        }
        String ordNo = System.currentTimeMillis() + result;
        return ordNo;
    }
}